package cn.annotation;

import cn.dao.EquipmentLogDAO;
import cn.factory.DAOFactory;
import cn.model.TEquipmentSysLog;
import cn.model.VUserRole;
import cn.util.Toolsutil;
import com.alibaba.fastjson.JSON;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;

/**
 * @desc 针对controller类中的方法进行增强切入，实现controller方法执行后的数据库日志存储
 */

@Aspect
public class EquipmentLogAspect {
    /**
     * 后置通知 用于拦截Controller.serverice中所有操作请求方法
     * 并根据所需进行日志记录的方法进行日志管理
     * @param joinPoint 切点
     */
    @AfterReturning(pointcut="execution(* cn.impl.*.*(..))",returning="rvt")
    public void setLog(JoinPoint joinPoint,Object rvt){
        //首先根据参照点方法的返回值来决定是否进行日志操作
        if(rvt instanceof Boolean){
            Boolean b = (Boolean)rvt;
            if(b.booleanValue() == false)
                return; //返回值为false，不做任何日志操作。
        }

        try {
            //通过切入目标方法的连接点 ，获取连接点的类名，方法名，参数名
            String targetName = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            Object[] arguments = joinPoint.getArgs();

            Class targetClass = Class.forName(targetName);
            Method[] methods = targetClass.getMethods();

            //通过注解获取Controller方法的操作类型和操作内容
            boolean isSaveLog = false;
            String operationType = "";
            String operationName = "";
            for (Method method : methods) {
                //System.out.println(method.getName());
                if (method.getName().equals(methodName)) {
                    Class[] clazzs = method.getParameterTypes();
                    if (clazzs.length == arguments.length) {
                        isSaveLog = method.getAnnotation(EquipmentLog.class).isSaveLog();
                        operationType = method.getAnnotation(EquipmentLog.class).operationType();
                        operationName = method.getAnnotation(EquipmentLog.class).operationName();
                        break;
                    }
                }
            }

            //如果方法注解的 isSaveLog属性为false，则不做日志管理
            if(isSaveLog==false) return;


            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            HttpSession session = request.getSession();
            //读取session中的管理员用户
            VUserRole user = (VUserRole) session.getAttribute("loginuser");
            //获得方法的参数
            Object[] args = joinPoint.getArgs();
            String param = "";
            for(int i=0;i<args.length;i++){
                param += JSON.toJSONString(args[i]);
            }

            /*System.out.println("ClassName=" + targetName);
            System.out.println("methodName=" + methodName);
            System.out.println("isSaveLog=" + isSaveLog);
            System.out.println("operationType=" + operationType);
            System.out.println("operationName=" + operationName);
            System.out.println("param=" + param);
            System.out.println("return=" + rvt);
            System.out.println("user=" + user.getUserid());*/

            if(rvt==null){
                return ; //不做日志管理
            }else if(rvt instanceof Boolean){
                if((Boolean)rvt==false) return;
            }else if(rvt instanceof Integer ||rvt instanceof Long){
                if((Integer)rvt <=0 ) return;
            }

            //向日志表中添加操作日志记录
            TEquipmentSysLog log = new TEquipmentSysLog();
            log.setOpertype(operationType);
            log.setDescription(operationName);
            log.setOpermethod(targetName+"、"+methodName);
            log.setRequestip("");
            log.setCreatedate(Toolsutil.getdatetimes());
            log.setUserid(user.getUserid());
            //保存日志数据到数据库中
            EquipmentLogDAO logdao = DAOFactory.getEquipmentLogDAO();
            logdao.addLog(log);

        }catch(NullPointerException e){
            //什么都不做
            //e.printStackTrace();
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

}